#ifndef _DFA_DEC
#define _DFA_DEC

#include "Buffer.h"
#include "Dfa_base.h"
#include "Dlex.h"
#include <iostream>
#include <list>
#include <string>

namespace automata {
	class Dfa {
	public:
		typedef int Attr;
		enum Dfa_type {Start_dfa, Suffix_dfa, Normal_dfa, Start_suffix_dfa };
		enum Dfa_state {Normal, Suffix, Acc, Rej};		// current dfa state
	public:
		Dfa(mylib::Buffer &in, dlex::Reg_def &def, std::ostream &err=std::cout, const Attr attribute=0, bool start=false);
		Dfa(const dfa_base::Dfa_base::State_type *dfa_tab, bool start=false);
		~Dfa() { delete tab; tab=0;}

		class Invalid_oper {};
		class Undef_err {};
		class Err_input {};
		class Err_reg {};
		const std::string &lexeme(){return _lexeme;}// get the matched string
		Attr &attr(){return _attr;}				// return the attribute for this dfa
		Dfa_type type(){return _type;}					// return the type
		Dfa_state move(char c, bool start=false);	// move 
		long read() {return _read_num;}			// return the read number
		bool to_nextcycle(bool start_line=false,const char *from=0, const char *to=0);//go to next cycle,wake up or not
		void write(std::ostream &out=std::cout, const std::string &name=""){
			if( name.length() )
				out << "size_t " << name << "[] = {\n";			// the head
			out << start_line << ", " << _type << ", " << _attr << ",\n";
			tab->write(out);
			out << "};\n";
		}
	private:
		Dfa(const Dfa &dfa) {}			// copy not allowed
		Dfa &operator=(const Dfa &dfa) {}
	private :
		enum _Dfa_state {_Start, _Start_matched, _Nor, _Suf};
		enum _Mode { _Match_mod, _Start_mod };
		struct _Sub_dfa {
			std::string _str;
			dfa_base::Dfa_base::State_type state;
			_Dfa_state status;
			bool start_time;
			_Sub_dfa(dfa_base::Dfa_base::State_type s, _Dfa_state stat){ state=s; status=stat; start_time=true; }
			_Sub_dfa() {}
		};
		std::list<_Sub_dfa> sub_dfa;
		Dfa_type _type;							// store the type
		Attr _attr;
		dfa_base::Dfa_base *tab;
		std::string _lexeme;					// the matched string
		int _read_num;							// the read number
		std::string mis_char;					// the missed characters for start condition
		_Mode mode;								// the dfa matching mode
		bool mis_start_line;					// missed start line
		bool start_line;							// to label whether it need to test the start
	};
}
#endif
